package cn.jufuns.util;

import java.beans.*;
import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.beanutils.*;
import org.apache.commons.beanutils.expression.Resolver;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import cn.jufuns.db.JDBC;

/**
 * bean处理工具 重写BeanUtils.copyBeanProperties方法，使得空值则不赋值
 * 
 * @author zxs
 *
 */
public class BeanUtil extends BeanUtilsBean {

	private Log log = LogFactory.getLog(BeanUtil.class);

	/**
	 * mapList转beanList
	 * 
	 * @param clazz
	 * @param mapList
	 * @return
	 * @throws IntrospectionException
	 * @throws IllegalAccessException
	 * @throws InstantiationException
	 * @throws InvocationTargetException
	 */
	public static List convertMap2BeanList(Class clazz, List mapList)
			throws IntrospectionException, IllegalAccessException,
			InstantiationException, InvocationTargetException {
		List voList = new ArrayList();

		for (int j = 0; j < mapList.size(); j++) {
			Map map = (Map) mapList.get(j);

			voList.add(BeanUtil.convertMap2Bean(clazz, map));
		}

		return voList;
	}

	/**
	 * map转bean
	 * 
	 * @param type
	 * @param map
	 * @return
	 * @throws IntrospectionException
	 * @throws IllegalAccessException
	 * @throws InstantiationException
	 * @throws InvocationTargetException
	 */
	public static Object convertMap2Bean(Class type, Map map)
			throws IntrospectionException, IllegalAccessException,
			InstantiationException, InvocationTargetException {
		BeanInfo beanInfo = Introspector.getBeanInfo(type); // 获取类属性
		Object obj = type.newInstance(); // 创建 JavaBean 对象

		// 给 JavaBean 对象的属性赋值
		PropertyDescriptor[] propertyDescriptors = beanInfo
				.getPropertyDescriptors();
		for (int i = 0; i < propertyDescriptors.length; i++) {
			PropertyDescriptor descriptor = propertyDescriptors[i];
			String propertyName = descriptor.getName();

			if (map.containsKey(propertyName)) {
				// 下面一句可以 try 起来，这样当一个属性赋值失败的时候就不会影响其他属性赋值。
				Object value = map.get(propertyName);

				Object[] args = new Object[1];
				args[0] = value;

				descriptor.getWriteMethod().invoke(obj, args);
			}
		}
		return obj;
	}

	/**
	 * Bean2Bean
	 * 
	 * @param clazz
	 * @param object
	 * @return
	 * @throws Exception
	 */
	public static Object convertBean2Bean(Class clazz, Object object)
			throws Exception {

		Object returnObj = clazz.getInterfaces();
		BeanUtils.copyProperties(returnObj, object);
		return returnObj;
	}

	/**
	 * 好使 ，用法TStoreCheck po = (TStoreCheck) BeanUtil.convertBean2Bean(new
	 * TStoreCheck(), checkVO);
	 * 
	 * @param returnObj
	 * @param object
	 * @return
	 * @throws Exception
	 */
	public static Object convertBean2Bean(Object returnObj, Object object)
			throws Exception {
		BeanUtil beanUtil = new BeanUtil();
		beanUtil.copyProperties(returnObj, object);

		return returnObj;
	}

	/**
	 * 好使
	 * 
	 * @param dest
	 * @param orig
	 * @throws IllegalAccessException
	 * @throws InvocationTargetException
	 */
	public static void copyBeanProperties(Object dest, Object orig)
			throws IllegalAccessException, InvocationTargetException {
		BeanUtil beanUtil = new BeanUtil();
		beanUtil.copyProperties(dest, orig);
	}

	public void copyProperties(Object dest, Object orig)
			throws IllegalAccessException, InvocationTargetException {
		if (dest == null)
			throw new IllegalArgumentException("No destination bean specified");
		if (orig == null)
			throw new IllegalArgumentException("No origin bean specified");
		if (log.isDebugEnabled())
			log.debug("BeanUtils.copyProperties(" + dest + ", " + orig + ")");
		if (orig instanceof DynaBean) {
			DynaProperty origDescriptors[] = ((DynaBean) orig).getDynaClass()
					.getDynaProperties();
			for (int i = 0; i < origDescriptors.length; i++) {
				String name = origDescriptors[i].getName();
				if (getPropertyUtils().isWriteable(dest, name)) {
					Object value = ((DynaBean) orig).get(name);

					if (value != null)
						copyProperty(dest, name, value);
				}
			}

		} else if (orig instanceof Map) {
			for (Iterator names = ((Map) orig).keySet().iterator(); names
					.hasNext();) {
				String name = (String) names.next();
				if (getPropertyUtils().isWriteable(dest, name)) {
					Object value = ((Map) orig).get(name);
					if (value != null)
						copyProperty(dest, name, value);

				}
			}

		} else {
			PropertyDescriptor origDescriptors[] = getPropertyUtils()
					.getPropertyDescriptors(orig);
			for (int i = 0; i < origDescriptors.length; i++) {
				String name = origDescriptors[i].getName();
				if (!"class".equals(name)
						&& getPropertyUtils().isReadable(orig, name)
						&& getPropertyUtils().isWriteable(dest, name))
					try {
						Object value = getPropertyUtils().getSimpleProperty(
								orig, name);
						if (value != null)
							copyProperty(dest, name, value);
					} catch (NoSuchMethodException e) {
					}
			}

		}
	}

	/**
	 * 去掉对象中的空格
	 * 
	 * @param javabean
	 *            对象
	 * @param exceptionalFields
	 *            非处理的属性，
	 * @param null2empty
	 *            是否将null转成""
	 * @throws IntrospectionException
	 * @throws IllegalAccessException
	 * @throws IllegalArgumentException
	 * @throws InvocationTargetException
	 */
	public static void trimObject(Object javabean, String[] exceptionalFields,
			boolean null2empty) throws IntrospectionException,
			IllegalAccessException, IllegalArgumentException,
			InvocationTargetException {
		if (javabean != null) {
			Class clz = javabean.getClass();
			List<Method> getters = JavaBase.getGetter(clz);
			for (Method getter : getters) {
				if (!JavaBase.isJavaString(getter.getReturnType()))
					continue;
				String fieldName = JavaBase.getFieldNameByGetter(getter
						.getName());
				if ((!ArrayUtil.isEmpty(exceptionalFields))
						&& (ArrayUtil.contains(exceptionalFields, fieldName))) {
					continue;
				}
				String setterName = JavaBase.getSetterByFieldName(fieldName);
				Method setter = JavaBase.getSetter(clz, setterName);

				String originalValue = (String) getter.invoke(javabean,
						new Object[0]);
				if (originalValue != null) {
					if (setter != null)
						setter.invoke(
								javabean,
								new Object[] { StringUtils.trim(originalValue) });
				} else if (null2empty)
					if (setter != null)
						setter.invoke(javabean, new Object[] { "" });
			}
		}
	}

	/**
	 * bean转成 map对象
	 * 
	 * @param bean
	 * @return
	 */
	public static Map<String, Object> bean2Map(Object bean) {
		try {
			Map<String, Object> beanMap = BeanUtils.describe(bean);
			return beanMap;
		} catch (IllegalAccessException e) {
			throw new RuntimeException("bean 转成 map异常", e);
		} catch (InvocationTargetException e) {
			throw new RuntimeException("bean 转成 map异常", e);
		} catch (NoSuchMethodException e) {
			throw new RuntimeException("bean 转成 map异常", e);
		}
	}

}
